package model

import (
	"context"
	"fmt"
	"time"

	"gitee.com/liuxuezhan/ar-platform/login-rpc/internal/dao/schema"
	"gitee.com/liuxuezhan/ar-platform/login-rpc/internal/svc"

	"github.com/zeromicro/go-zero/core/logc"
	"gorm.io/gorm"
)

type UserModel struct {
	ctx context.Context
	db  *gorm.DB
}

func NewUserModel(ctx context.Context, db *gorm.DB) *UserModel {
	return &UserModel{
		ctx: ctx,
		db:  db,
	}
}

func (model *UserModel) getDb() *gorm.DB {
	if model.db != nil {
		return model.db
	}

	return svc.Db
}

func (model *UserModel) InsertSchema(data *schema.User, userId int64) error {
	t := time.Now().Unix()
	data.CreatedAt = t
	data.UpdatedAt = t
	data.RegisterTime = t
	data.LastOnlineTime = t

	table := schema.SubtableUserId(userId, data.TableName())
	dbRes := model.getDb().Model(&schema.User{}).Table(table).Create(data)
	if err := dbRes.Error; err != nil {
		logc.Error(model.ctx, "UserModel-InsertSchema,err:", err)
		return err
	}

	return nil
}

func (model *UserModel) GetPasswordByUserId(userId int64) (password string, err error) {
	table := schema.SubtableUserId(userId, schema.User{}.TableName())
	dbRes := model.getDb().Model(&schema.User{}).Table(table).Select("password").Where("id =?", userId).First(&password)
	if err := dbRes.Error; err != nil && err != gorm.ErrRecordNotFound {
		logc.Error(model.ctx, "UserModel-GetPasswordByUserId,err:", err)
		return password, err
	}

	return password, nil
}

func (model *UserModel) GetUserByUserId(userId int64) (user schema.User, err error) {
	table := schema.SubtableUserId(userId, schema.User{}.TableName())
	dbRes := model.getDb().Model(&schema.User{}).Table(table).Where("id =?", userId).First(&user)
	if err := dbRes.Error; err != nil && err != gorm.ErrRecordNotFound {
		logc.Error(model.ctx, "UserModel-GetUserByUserId,err:", err)
		return user, err
	}

	return user, nil
}

func (model *UserModel) GetGoogleByUserId(userId int64) (user schema.User, err error) {
	table := schema.SubtableUserId(userId, schema.User{}.TableName())
	dbRes := model.getDb().Model(&schema.User{}).Table(table).Select("is_google,is_binding_google,google_code").Where("id =?", userId).First(&user)
	if err := dbRes.Error; err != nil {
		logc.Error(model.ctx, "UserModel-GetGoogleByUserId,err:", err)
		return user, err
	}

	return user, nil
}

func (model *UserModel) UpdateUserPassword(userId int64, password string) error {
	table := schema.SubtableUserId(userId, schema.User{}.TableName())
	dbRes := model.getDb().Model(&schema.User{}).Table(table).Where("id=?", userId).Update("password", password)
	if err := dbRes.Error; err != nil {
		logc.Error(model.ctx, "UserModel-UpdateUserPassword,err:", err)
		return err
	}

	return nil
}

func (model *UserModel) UpdateUserIsGoogle(userId int64, isGoogle int32) error {
	table := schema.SubtableUserId(userId, schema.User{}.TableName())
	dbRes := model.getDb().Model(&schema.User{}).Table(table).Where("id=?", userId).Update("is_google", isGoogle)
	if err := dbRes.Error; err != nil {
		logc.Error(model.ctx, "UserModel-UpdateUserIsGoogle,err:", err)
		return err
	}

	return nil
}

func (model *UserModel) UpdateUserGoogleCode(userId int64, googleCode string) error {
	table := schema.SubtableUserId(userId, schema.User{}.TableName())
	dbRes := model.getDb().Model(&schema.User{}).Table(table).Where("id=?", userId).Update("google_code", googleCode)
	if err := dbRes.Error; err != nil {
		logc.Error(model.ctx, "UserModel-UpdateUserPassword,err:", err)
		return err
	}

	return nil
}

func (model *UserModel) UpdateLastOnlineTime(user schema.User) error {
	table := schema.SubtableUserId(user.Id, schema.User{}.TableName())
	dbRes := model.getDb().Model(&schema.User{}).Table(table).Where("id=?", user.Id).Updates(user)
	if err := dbRes.Error; err != nil {
		logc.Error(model.ctx, "UserModel-UpdateLastOnlineTime,err:", err)
		return err
	}

	return nil
}

// 获取用注册时间
func (model *UserModel) GetUserRegisterTimeByUserId(userId int64) (t int64, err error) {
	table := schema.SubtableUserId(userId, schema.User{}.TableName())
	dbRes := model.getDb().Model(&schema.User{}).Table(table).Select("created_at").Where("id =?", userId).First(&t)
	if err := dbRes.Error; err != nil {
		logc.Error(model.ctx, "UserModel-GetUserRegisterTimeByUserId,err:", err)
		return t, err
	}

	return t, nil
}

// 获取同一IP绑定数量
func (model *UserModel) GetIPNumByIP(ip string) (t int64, err error) {
	var count int64
	dbRes := model.getDb().Model(&schema.UserTotal{}).Where("ip =?", ip).Count(&count)
	if err := dbRes.Error; err != nil {
		logc.Error(model.ctx, "UserModel-GetUserRegisterTimeByUserId,err:", err)
		return count, err
	}

	return count, nil
}

func (model *UserModel) UpdateUserFirstLoginTime(userId int64, firstLoginTime int64) error {
	table := schema.SubtableUserId(userId, schema.User{}.TableName())
	dbRes := model.getDb().Model(&schema.User{}).Table(table).Where("id=?", userId).Update("first_login_time", firstLoginTime)
	if err := dbRes.Error; err != nil {
		logc.Error(model.ctx, "UserModel-UpdateUserPassword,err:", err)
		return err
	}

	return nil
}

func (model *UserModel) Logout(userIds ...int64) error {
	userTableMap := make(map[string][]int64, 3)
	for _, userId := range userIds {
		table := schema.SubtableUserId(userId, schema.User{}.TableName())
		userTableMap[table] = append(userTableMap[table], userId)
	}
	for table, uids := range userTableMap {
		dbRes := model.getDb().Model(&schema.User{}).Table(table).Where("user_id in ?", uids).Updates(map[string]interface{}{
			"is_online": 0,
		})
		if err := dbRes.Error; err != nil {
			return fmt.Errorf("logout error: %v", err)
		}
	}

	return nil
}
